#ifndef __BSPFILE_HPP__
#define __BSPFILE_HPP__

#include "../tdp2/tdp2_math.hpp"
#include "../../rdx/src/rdx/rdx_basictypes.hpp"

namespace BSPFile
{
	using namespace RDX;
	using namespace TDP::Math;

	const unsigned int NumLODLevels_k = 8;
	const unsigned int NumLightCoefs_k = 9;		// 3-band SH

	enum
	{
		FaceTypePlanar_k  = 1,
		FaceTypePatch_k   = 2,
		FaceTypeTriMesh_k = 3,
		FaceTypeSprite_k  = 4,
	};

	enum
	{
		SceneFlagMirror_k = 1,
		SceneFlagNearplane_k = 2,
		SceneFlagClearDepth_k = 4,
		SceneFlagAlwaysVisible_k = 8,
		SceneFlagNearplaneInverted_k = 16,
	};

	enum
	{
		LightModeOmni_k,
		LightModeDirectional_k,
		LightModeCubeMap_k,
		LightModeProjected_k,
		LightModeSky_k,
	};

	struct BSPPlane_D
	{
		FVec3 normal;
		Float32 dist;

		void Swap();
	};

	// Shared structures
	struct BSPCommonVert
	{
		FVec3 position;		// 0
		FVec3 svec;			// 12
		FVec2 texCoords;		// 24
		FVec4 tvecN;			// 32
		FVec2 lightmapTexCoords;
	};

	struct BSPVertex_D
	{
		FVec3 position;
		FVec2 texCoords;
		FVec2 lightMapTexCoords;
		FVec3 normal;
		FVec3 svec;
		FVec3 tvec;

		void Swap();
	};

	struct BSPModel_D
	{
		FVec3 mins;
		FVec3 maxs;
		FVec3 gridSize;
		FVec3 gridOrigin;
		Int32 gridBounds[3];
		Float32 gridScalar;
		UInt32 face;
		UInt32 numFaces;
		UInt32 brush;
		UInt32 numBrushes;

		void Swap();
	};

	struct BSPIndex_D
	{
		UInt32 idx;

		void Swap();
	};

	struct BSPAreaPortal_D
	{
		Int32	leaf;
		UInt32	firstWinding;
		UInt32	numWindings;

		void Swap();
	};

	struct BSPAreaPortalWinding_D
	{
		UInt32	firstPoint;
		UInt32	numPoints;
		Int32	outsideArea;
		UInt32	plane;

		void Swap();
	};
	
	struct BSPAreaPortalPoint_D
	{
		FVec3 point;

		void Swap();
	};
	
	enum
	{
		BSPFaceNumLinkedScenes_k = 2,
	};

	struct BSPFace_D
	{
		UInt32 texture;
		UInt32 smoothingGroup;
		Int32 effect;		// -1 = None
		UInt32 faceType;
		UInt32 vertex;
		UInt32 numVertexes;
		UInt32 meshVert;
		UInt32 numMeshVerts;
		Int32 lightMap;
		Int32 lightMapCoords[2];
		Int32 lightMapSize[2];
		FVec3 lightMapOrigin;

		FVec3 lightMapMatrix[3];	// LightMapMatrix[2] = normal

		Int32 patchDimensions[2];

		Int32	linkedScenes[BSPFaceNumLinkedScenes_k];

		void Swap();
	};

	
	struct BSPBrush_D
	{
		unsigned int brushside;
		unsigned int numBrushSides;
		unsigned int texture;

		void Swap();
	};

		enum
	{
		BSPLumpEntities_k,
		BSPLumpTextures_k,
		BSPLumpPlanes_k,
		BSPLumpNodes_k,
		BSPLumpLeafs_k,
		BSPLumpLeafFaces_k,	// Index into Faces
		BSPLumpLeafBrushes_k,	// Index into Brushes
		BSPLumpModels_k,
		BSPLumpBrushes_k,
		BSPLumpBrushSides_k,
		BSPLumpVertexes_k,
		BSPLumpMeshVerts_k,
		BSPLumpEffects_k,
		BSPLumpFaces_k,
		BSPLumpLightMaps_k,
		BSPLumpLightVols_k,
		BSPLumpVisData_k,
		BSPLumpScenes_k,
		BSPLumpRTLights_k,
		BSPLumpAreaPortals_k,
		BSPLumpAreaPortalWindings_k,
		BSPLumpAreaPortalPoints_k,

		BSPLumpCount_k,
	};

	struct BSPLump_D
	{
		unsigned int offset;
		unsigned int length;
	};

	struct BSPHeader_D
	{
		unsigned int magic;	// Should be 0x50534249
		unsigned int version;	// Should be 0x0000002e
		BSPLump_D lumps[BSPLumpCount_k];
	};

	enum
	{
		BSPSurfaceFlagInvisible_k = 0x80000,
	};

	struct BSPTextureInfo_D
	{
	    char materialName[64];
		UInt32 surfaceFlags;
		UInt32 contentFlags;

		void Swap();
	};

	struct BSPNode_D
	{
		UInt32 planeIndex;
		Int32 children[2];	// Negative numbers are leafs, -(leaf+1)
		Int32 mins[3];
		Int32 maxs[3];

		void Swap();
	};

	struct BSPLeaf_D
	{
		Int32 cluster;
		UInt32 area;
		Int32 mins[3];
		Int32 maxs[3];
		UInt32 leafFace;
		UInt32 numLeafFaces;
		UInt32 leafBrush;
		UInt32 numLeafBrushes;

		void Swap();
	};

	struct BSPBrushSide_D
	{
		UInt32 plane;
		UInt32 texture;

		void Swap();
	};


	struct BSPEffect_D
	{
		char materialName[64];
		UInt32 brush;
		Int32 sceneVolume;		// scene volume number
		Int32 brushSide;			// -1 = none
		FVec3 fogColor;
		Float32 fogDensityScalar;

		void Swap();
	};

	struct BSPLightVolumeValues_D
	{
		Int32 coefs[9][256][3];

		void Swap();
	};

	struct BSPLightVolume_D
	{
		UInt8 shCoefs[9][3];
		UInt8 mult;

		void Swap();
	};

	struct BSPScene_D
	{
		Int32		target;				// -1 = framebuffer, anything else = proxy texture ID
		Int32		visibleInVolume;	// volume the scene is visible from, -1 = current volume
		Int32		drawInVolume;		// scene volume to draw objects in
		Int32		planeNum;			// nearplane plane number
		Int32		sceneFlags;

		void Swap();
	};

	struct BSPRTLight_D
	{
		Int32		mode;
		FVec3		origin;
		FVec3		color;

		// For projected and sky, this is the matrix
		// For directional, 0, 1, 2 = normal, 3 = inner falloff, 4 = outer falloff
		// For omni, 0 = radius
		Float32		parameters[9];

		void Swap();
	};
}

#endif

